Props avanzate
Le props sono il principale meccanismo di comunicazione tra componenti in React. Oltre all’uso base, esistono pattern avanzati che permettono di scrivere componenti più flessibili, riutilizzabili e scalabili.
Props come contratto tra componenti
Un componente React deve essere progettato come una funzione pura che riceve un insieme di input (props) e restituisce UI. Le props rappresentano un vero e proprio contratto tra il componente che fornisce i dati e quello che li consuma.
Ogni componente dovrebbe:
- Ricevere solo le props di cui ha realmente bisogno
- Non modificare mai direttamente le props
- Essere prevedibile rispetto ai valori ricevuti
Questo approccio rende il componente più semplice da testare e riutilizzare.
Spread operator nelle props
Lo spread operator permette di passare un insieme di props in modo compatto, evitando ripetizioni inutili.
Spread di oggetti props
function Button(props) {
return <button {...props} />
}
const buttonProps = {
type: "button",
disabled: false,
className: "primary"
}
<Button {...buttonProps} />
In questo caso tutte le proprietà dell’oggetto vengono passate al componente. È una tecnica utile quando si lavora con componenti wrapper o componenti altamente configurabili.
Ordine di applicazione delle props
Quando si combinano props esplicite e spread, l’ordine è fondamentale.
<button {...props} disabled />
La prop disabled sovrascrive eventuali valori presenti in props.
<button disabled {...props} />
In questo caso è props.disabled ad avere la precedenza.
Spread operator e children
Lo spread operator non include automaticamente children se non è presente nell’oggetto.
function Card(props) {
return <div className="card" {...props} />;
}
Se props contiene children, verranno renderizzati correttamente. In caso contrario, il componente risulterà vuoto.
Funzioni come props
Passare funzioni come props è uno dei pattern più importanti di React. Permette ai componenti figli di comunicare eventi o cambiamenti di stato al componente genitore.
Callback per la gestione degli eventi
function Button({ onClick }) {
return <button onClick={onClick}>Clicca</button>;
}
function App() {
const handleClick = () => {
console.log("Click gestito dal genitore");
};
return <Button onClick={handleClick} />;
}
Il componente figlio non conosce la logica dell’evento, ma si limita a invocare la funzione ricevuta.
Passaggio di parametri alle funzioni
Quando è necessario passare dati alla funzione, si utilizza una funzione anonima.
<button onClick={() => onSelect(id)}>Seleziona</button>
Questo consente di mantenere il controllo della logica nel componente genitore.
Funzioni come props e stato
Le funzioni come props vengono spesso usate per modificare lo stato del componente genitore.
function Counter({ increment }) {
return <button onClick={increment}>+</button>;
}
function App() {
const [count, setCount] = React.useState(0);
const increment = () => setCount(count + 1);
return <Counter increment={increment} />;
}
Questo pattern mantiene lo stato centralizzato e migliora la prevedibilità dell’applicazione.
Funzioni come render props
Una funzione può essere usata per definire cosa renderizzare, non solo per gestire eventi.
function List({ items, renderItem }) {
return <ul>{items.map((item) => renderItem(item))}</ul>;
}
<List items={[1, 2, 3]} renderItem={(item) => <li key={item}>{item}</li>} />;
Questo approccio aumenta notevolmente la flessibilità del componente.
Best practice per props avanzate
- Evitare di passare oggetti props non necessari
- Usare lo spread operator solo quando migliora la leggibilità
- Dare nomi chiari e coerenti alle funzioni passate come props
- Mantenere la logica di stato nei componenti più alti possibile
- Preferire componenti semplici e prevedibili
Le props avanzate sono uno strumento fondamentale per costruire componenti React modulari, riutilizzabili e facilmente manutenibili.